﻿//-----------------------------------------------------------------------
// <copyright>
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// </copyright>
//----------------------------------------------------------------------- 
namespace Fulcrum.ViewModelGenerator
{
    #region Usings

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    using System.Diagnostics;

    #endregion Usings

    public class ViewModelPropertyXmlConfiguration : IViewModelPropertyConfiguration
    {
        #region Properties
    
        public string Name { get; private set; }
        public string Type { get; private set; }
        public string DefaultValue { get; private set; }

        public bool IsValidated { get; private set; }
        public PropertyVisibility SetPropertyVisibility { get; private set; }

        public bool IsSerializable { get; private set; }

        public PropertyComparison Comparison { get; private set; }
        public StringComparison StringComparison { get; private set; }

        public string Summary { get; private set; }
        public string Remarks { get; private set; }

        public string FieldName
        {
            get
            {
                Debug.Assert(this.Name.Length > 0);

                var remainder = String.Empty;
                if (this.Name.Length > 1)
                {
                    remainder = this.Name.Substring(1, this.Name.Length - 1);
                }

                return String.Format("_{0}{1}",
                    this.Name[0].ToString().ToLowerInvariant(),
                    remainder);
            }
        }

        #endregion Properties

        #region Ctor

        public ViewModelPropertyXmlConfiguration(XElement xml)
        {
            if (null == xml)
            {
                throw new ArgumentNullException("xml");
            }

            if ("Property" != xml.Name)
            {
                throw new ArgumentException("Element 'Property' expected", "xml");
            }

            this.Parse(xml);
        }

        #endregion Ctor

        #region Parse

        private void Parse(XElement xml)
        {
            Debug.Assert(null != xml && "Property" == xml.Name);

            this.Name = this.ParseName(xml);
            this.Type = (string)xml.RequiredAttribute("Type");
            this.DefaultValue = (string)xml.RequiredAttribute("DefaultValue");

            this.IsValidated = (bool)xml.OptionalAttribute("ValidateValue", false);
            this.IsSerializable = (bool)xml.OptionalAttribute("Serializable", true);

            this.SetPropertyVisibility = xml.OptionalEnumAttribute<PropertyVisibility>("SetterVisibility", PropertyVisibility.Public);
            this.Comparison = xml.OptionalEnumAttribute<PropertyComparison>("Comparison", PropertyComparison.Equals);
            this.StringComparison = xml.OptionalEnumAttribute<StringComparison>("StringComparison", StringComparison.Ordinal);

            this.Summary = (string)xml.RequiredAttribute("Summary");
            this.Remarks = (string)xml.OptionalAttribute("Remarks", String.Empty);
        }

        private string ParseName(XElement xml)
        {
            var name = (string)xml.RequiredAttribute("Name");

            Debug.Assert(name.Length > 0);
            if (Char.IsLower(name[0]))
            {
                throw new ArgumentException("The property name must start with a uppercase letter", "Name");
            }

            return name;
        }

        #endregion Parse
    }
}
